<!--模块预览组件-->
<template>
  <div
    class="previewThePage"
    :style="{
      padding: terminalType === DESKTOP ? `0% ${cssStyle.paddingPercent}%` : '1%',
      'background-image': `url(${getImageUrl()})`,
    }"
    v-loading.fullscreen.lock="loading"
    element-loading-text="正在提交中..."
    data-blank="blankPage"
  >
    <grid-layout
      :layout.sync="templatePage.map(item => item.cssStyle)"
      :colNum="MAX_COL_NUM"
      :rowHeight="baseHeight"
      :margin="[baseHeight, baseHeight]"
      :is-resizable="processStatus(EDIT_STATUS)"
      :is-draggable="processStatus(EDIT_STATUS)"
      :vertical-compact="true"
      :use-css-transforms="false"
      :verticalCompact="true"
      :auto-size="false"
      :key="renderKey"
      @layout-ready="layoutReadyEvent"
    >
      <grid-item
        v-for="(item, index) in templatePage"
        :key="item.cssStyle.i"
        class="body-item"
        :x="item.cssStyle.x"
        :y="item.cssStyle.y"
        :w="item.cssStyle.w"
        :h="item.cssStyle.h"
        :i="item.cssStyle.i"
        :id="item.cssStyle.i"
        @moved="moveEventEnd"
        :style="previewTheStyle(item)"
        @click="processStatus(EDIT_STATUS) && templateSelection(item, index)"
        v-dragscroll
        :data-index="item.cssStyle.i"
        :data-moduleId="item.moduleId"
        :class="borderSwitching(item, index)"
        @resized="resizedEvent"
        :isResizable="item.moduleId !== BEAUTIFUL_MOBILE_NAME && processStatus(EDIT_STATUS)"
      >
        <!-- 根据模块 ID 渲染不同内容 -->
        <Component
          :is="componentMap[item.moduleId]"
          v-model:cssStyle="item.cssStyle"
          v-model:businessData="item.businessData"
          v-model:vote="item.vote"
          :deliveryStatus="deliveryStatus"
          :terminalType="terminalType"
        />
        <!--复制删除按钮-->
        <div class="item-operation" v-if="processStatus(EDIT_STATUS)">
          <el-icon v-if="templatePageIndex === index" @click.stop="templatesAreCopiedAndAdded(item)"><DocumentCopy /></el-icon>
          <el-icon v-if="templatePageIndex === index" @click.stop="deleteBtn(templatePage, item.cssStyle.i)"><Delete /></el-icon>
        </div>
      </grid-item>
      <grid-item
        :x="MAX_COL_NUM"
        :y="buttonYCoordinates"
        :w="MAX_COL_NUM"
        :h="5"
        :i="MAX_COL_NUM"
        style="text-align: center"
        id="bottomItem"
        :isResizable="false"
        :isDraggable="false"
      >
        <el-button
          type="danger"
          @click="calibration"
          :style="button_FontSize"
          class="body-btn"
          v-if="processStatus(PREVIEW_STATUS)"
        >
          完整性校验
        </el-button>
        <el-button
          type="success"
          @click="checkSubmit"
          class="body-btn"
          v-if="processStatus(PREVIEW_STATUS)"
          :style="button_FontSize"
        >
          提交规则校验
        </el-button>
        <el-button
          type="danger"
          @click="submit"
          class="body-btn"
          v-if="processStatus(SUBMISSION_STATUS) && submitButton"
          :style="button_FontSize"
        >
          提交
        </el-button>
      </grid-item>
    </grid-layout>
  </div>
</template>

<script setup>
import {
  BEAUTIFUL_MOBILE_NAME,
  BUTTON_FONTS,
  DEVICE_TYPE,
  MAX_COL_NUM,
  MODULE_TYPE,
  PROCESS_TYPE,
  SCALE_CONFIGURATION,
  SELECTED_STATUS,
  UNCHECKED,
  UNCHECKED_STATUS,
} from "@/utils/mockConfiguration/mockConfig";
import { v4 } from "uuid";
import Qs from "qs";
import PicturePreview from "@/components/PreviewTheModule/picturePreview.vue";
import TextPreview from "@/components/PreviewTheModule/textPreview.vue";
import RichTextPreview from "@/components/PreviewTheModule/richTextPreview.vue";
import VotingPreview from "@/components/PreviewTheModule/votingPreview.vue";
import ChoiceQuestionPreview from "@/components/PreviewTheModule/choiceQuestionPreview.vue";
import ShortAnswerQuestionPreview from "@/components/PreviewTheModule/shortAnswerQuestionPreview.vue";
import ParticipationRatePreview from "@/components/PreviewTheModule/participationRatePreview.vue";
import { useTemplateEditing } from "@/store/modules/templateEditing";
import Conf from "@/utils/conf";
import { Delete, DocumentCopy } from "@element-plus/icons-vue";
import useSubmitTheVerification from "@/utils/previewTheConfiguration";
import useEditThePage from "@/utils/editTheConfiguration";
import useInitializationMethod from "@/utils/initializationMethod";

const { SCALED_FIXED_SCALE_MODULE } = MODULE_TYPE;
const { SUBMISSION_STATUS, PREVIEW_STATUS, EDIT_STATUS } = PROCESS_TYPE;
const { DESKTOP } = DEVICE_TYPE;
const templateEditing = useTemplateEditing();
const { templateSelection, updateDimensions } = templateEditing;
const { templatePage, templatePageIndex, selectedModules, renderKey, baseHeight, buttonYCoordinates, submitButton } =
  storeToRefs(templateEditing);
const cssStyle = computed(() => templateEditing.currentSettings.baseConfig.cssStyle); //基础配置样式
const { init } = useInitializationMethod(); //初始化方法、必填题规则、选填题规则、禁答题规则
const { checkSubmit, submit, loading, calibration } = useSubmitTheVerification(); //提交规则校验
const { templatesAreCopiedAndAdded, moveEventEnd, deleteBtn } = useEditThePage(); //模板复制添加、移动、删除

//根据模块 ID 获取对应的组件
const componentMap = {
  image: PicturePreview,
  text: TextPreview,
  richText: RichTextPreview,
  beautifulMobilePerson: VotingPreview,
  choiceQuestion: ChoiceQuestionPreview,
  shortAnswerQuestion: ShortAnswerQuestionPreview,
  participationRate: ParticipationRatePreview,
  scoreObtained: ParticipationRatePreview,
};
const props = defineProps({
  deliveryStatus: {
    type: String,
    required: true,
    default: PROCESS_TYPE.EDIT_STATUS, //EDIT_STATUS:编辑状态,PREVIEW_STATUS:预览状态,DELIVERY_STATUS:下发状态,SUBMISSION_STATUS:提交状态,
  }, //流程状态，默认编辑状态
  terminalType: {
    type: String,
    required: true,
    default: DEVICE_TYPE.DESKTOP, //DESKTOP:pc端,MOBILE:移动端
  },
});

/**
 * 当前流程状态
 * @param type 状态类型
 */
const processStatus = type => props.deliveryStatus === type;

/**
 * 适配字体
 */
const button_FontSize = computed(() => {
  const fontSize = BUTTON_FONTS * SCALE_CONFIGURATION[props.terminalType];
  return {
    fontSize: `${fontSize}rem`,
    padding: `${fontSize}rem`,
  };
});

/**
 * 预览样式
 * @param location 模块位置
 * @param paddingPercent 模块内边距
 * @param backgroundColor 模块背景色
 */
const previewTheStyle = ({ cssStyle: { location, paddingPercent, backgroundColor } }) => ({
  justifyContent: location,
  padding: `${paddingPercent}%`,
  backgroundColor,
});

/**
 * 边框切换
 * @param item 模块数据
 * @param index 选择的模块索引
 */
const borderSwitching = (item, index) => {
  if (templatePageIndex.value === index || selectedModules.value.includes(item.cssStyle.i)) {
    return SELECTED_STATUS;
  }
  return templatePageIndex.value !== null ? UNCHECKED_STATUS : UNCHECKED;
};

/**
 * 模块大小改变
 * @param i 模块的i值
 * @param newH 新的高度
 * @param newW 新的宽度
 * @param newHPx 新的高度的px值
 * @param newWPx 新的宽度的px值
 */
const resizedEvent = (i, newH, newW, newHPx, newWPx) => {
  //查找当前正在拖动的图片模块的样式，templatePage是配置固定写死的，所以一定会有cssStyle
  const { cssStyle } = templatePage.value?.find(
    ({ moduleId, cssStyle: { i: id } }) => SCALED_FIXED_SCALE_MODULE.includes(moduleId) && i === id,
  );
  cssStyle.aspectRatio = newHPx / newWPx;
};

/**
 * 获取图片URL的函数
 */
const getImageUrl = () => {
  const { backgroundImageId } = cssStyle.value;
  if (backgroundImageId === "") {
    return new URL("", import.meta.url).href;
  }
  const queryParams = Qs.stringify({ id: backgroundImageId });
  return `${Conf.VITE_APP_BASE_API}/biz/common/image/loading?${queryParams}`;
};

/**
 * 监听布局完成,修改富文本模块的样式
 */
const layoutReadyEvent = () => {
  if (props.terminalType === DESKTOP) {
    return;
  }
  const richTextNodes = document.querySelectorAll(".content-richText p, .content-richText span"); //所有富文本模块节点
  richTextNodes.forEach(item => {
    //获取元素的计算样式
    const computedStyle = window.getComputedStyle(item);
    //获取字体大小
    const fontSize = parseFloat(computedStyle.fontSize);
    const { style } = item;
    style.fontSize = `${fontSize * SCALE_CONFIGURATION[props.terminalType]}rem`;
  });
};

onMounted(() => {
  init(props);
  window.addEventListener("resize", updateDimensions);
  window.addEventListener("load", updateDimensions);
  updateDimensions(v4());
});
</script>

<style scoped lang="less">
.previewThePage {
  flex: 1;
  width: 100%;
  height: 100%;
  background-repeat: no-repeat;
  background-size: cover; /* 使背景图片覆盖整个容器 */
  overflow: hidden;
  overflow-y: auto;
  &::-webkit-scrollbar {
    display: none;
  }
  //拖动模块
  :deep(.body-item) {
    .item-content {
      box-sizing: border-box;
      position: relative;
      display: flex;
      width: 100%;
    }
    //拖动图标
    .vue-resizable-handle {
      width: 7px;
      height: 7px;
      padding: 0;
      background-size: 100% 100%;
    }
    //拖拽模块的复制和删除按钮
    .item-operation {
      position: absolute;
      top: 5px;
      right: 0;
      display: flex;
      column-gap: 5px;
      .el-icon {
        font-size: 20px;
        cursor: pointer;
        color: @buttonColor;
      }
    }
  }
  //提交按钮
  .body-btn {
    padding: 18px;
  }
  //非选中拖拽样式
  .item-drag {
    outline: 2px dashed #e3e3e3;
  }
  //选中样式
  .item-active {
    outline: 2px dashed @buttonColor;
  }
  //默认样式
  .item-default {
    outline: none;
  }
}
</style>
